//
//  ClientBlue.m
//  blue_classic_plus
//
//  Created by os on 1/19/24.
//

#import "ClientBlue.h"

#define ClientStateType @"clientState"
#define ServerMsgType @"serverMsg"

@implementation ClientBlue


// 返回的给flutter的标准结构
- (void) toFlutterType:(NSString *)type code:(NSNumber *)code msg:(NSString *)msg{
    
    NSMutableDictionary * dic = [NSMutableDictionary dictionary];
    dic[@"type"] = type;
    if (code != nil) {
        dic[@"code"] = code;
    }
    if (msg != nil) {
        dic[@"msg"] = msg;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        self.sink(dic);
    });
    
}


// 初始化方法
- (instancetype)initWithSink:(FlutterEventSink)sink uuid: (NSString *)uuid name:(nonnull NSString *)name {
  self = [super init];
  if (self) {
      self.sink = sink;
      self.uuid = uuid;
      self.name = name;
    // 创建一个 CBCentralManager 对象，指定代理和队列
    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
    // 创建一个 CBUUID 对象，根据传入的 UUID 字符串
    self.characteristicUUID = [CBUUID UUIDWithString:uuid];
  }
  return self;
}

// 开始扫描的方法
- (void)startScan: (CBCentralManager *)central {
  // 判断蓝牙状态是否可用
  if (central.state == CBManagerStatePoweredOn) {
      self.isConnecting = true;
    // 开始扫描周围的蓝牙外设，不指定服务 UUID，扫描所有外设
    //NSArray *serviceUUIDs =  @[self.characteristicUUID];
      [central scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];
  }
}

// 结束扫描
- (void)stopScan{
    [self.centralManager stopScan];

}

// 结束连接
- (void)bluetoothStopConnect{
    
    if (self.peripheral != nil) {
        [self.centralManager cancelPeripheralConnection:self.peripheral];
    }
    self.isConnecting = false;
}

#pragma mark CBCentral代理方法
// 当蓝牙状态改变时的回调
- (void)centralManagerDidUpdateState: (CBCentralManager *)central {
    /**
     CBManagerStateUnknown = 0,
     CBManagerStateResetting,
     CBManagerStateUnsupported,
     CBManagerStateUnauthorized,
     CBManagerStatePoweredOff,
     CBManagerStatePoweredOn,
     */
    NSLog(@"ClientBlue 状态: %ld", (long)central.state);
    // 如果状态为开启，尝试启动服务端
    if (central.state == CBManagerStatePoweredOn) {
        [self startScan:central];
    } else {
        if (self.sink != nil) {
            [self toFlutterType:ClientStateType code:@(central.state) msg:@"蓝牙状态不是CBManagerStatePoweredOn"];
        }
        self.isConnecting = false;
    }
}

// 当发现外设时的回调
- (void)centralManager: (CBCentralManager *)central didDiscoverPeripheral: (CBPeripheral *)peripheral advertisementData: (NSDictionary<NSString *,id> *)advertisementData RSSI: (NSNumber *)RSSI {
    
    //NSLog(@"ClientBlue 扫描到的蓝牙设备有：%@ at %@",advertisementData[CBAdvertisementDataLocalNameKey],peripheral.name);
    
    NSString *serverKeyName = advertisementData[CBAdvertisementDataLocalNameKey];
    if ([serverKeyName isEqualToString:self.name]) {
        // 停止扫描
        [central stopScan];
        // 保存外设对象
        self.peripheral = peripheral;
        // 连接外设
        [central connectPeripheral:peripheral options:nil];
    }
}

// 当连接外设成功时的回调
- (void)centralManager: (CBCentralManager *)central didConnectPeripheral: (CBPeripheral *)peripheral {
    //NSLog(@"ClientBlue 连接外设成功：%@", peripheral.name);
    
  // 设置外设的代理
  peripheral.delegate = self;
  // 发现外设的服务，传 nil 表示不过滤
  [peripheral discoverServices:nil];
}

// 当连接外设失败时的回调
- (void)centralManager: (CBCentralManager *)central didFailToConnectPeripheral: (CBPeripheral *)peripheral error: (NSError *)error {
  //NSLog(@"ClientBlue 连接外设失败：%@，错误：%@", peripheral.name, error.localizedDescription);
    [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    self.isConnecting = false;
}

// 当断开外设连接时的回调
- (void)centralManager: (CBCentralManager *)central didDisconnectPeripheral: (CBPeripheral *)peripheral error: (NSError *)error {
    
    [central cancelPeripheralConnection:peripheral];
    [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
  
    self.peripheral = nil;
    self.isConnecting = false;
}



#pragma mark CBPeripheral代理方法
// 当发现外设的服务时的回调
- (void)peripheral: (CBPeripheral *)peripheral didDiscoverServices: (NSError *)error {
  if (error) {
    NSLog(@"ClientBlue 发现服务错误：%@", error.localizedDescription);
      self.isConnecting = false;
      [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    return;
  }
  // 遍历外设的服务
  for (CBService *service in peripheral.services) {
    NSLog(@"ClientBlue 发现服务：%@", service.UUID.UUIDString);
    // 发现服务的特征，传 nil 表示不过滤
    [peripheral discoverCharacteristics:nil forService:service];
  }
}

// 当发现服务的特征时的回调
- (void)peripheral: (CBPeripheral *)peripheral didDiscoverCharacteristicsForService: (CBService *)service error: (NSError *)error {
  if (error) {
    NSLog(@"ClientBlue 发现特征错误：%@", error.localizedDescription);
    self.isConnecting = false;
      [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    return;
  }
  // 遍历服务的特征
  for (CBCharacteristic *characteristic in service.characteristics) {
    NSLog(@"ClientBlue 发现特征：%@", characteristic.UUID.UUIDString);
    // 判断特征的 UUID 是否是要订阅的
    if ([characteristic.UUID isEqual:self.characteristicUUID]) {
      // 订阅该特征
      [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    }
  }
}

// 当订阅特征的状态改变时的回调
- (void)peripheral: (CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic: (CBCharacteristic *)characteristic error: (NSError *)error {
  if (error) {
    NSLog(@"ClientBlue 更新通知状态错误：%@", error.localizedDescription);
      self.isConnecting = false;
      [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    return;
  }
  // 判断是否订阅成功
  if (characteristic.isNotifying) {
    NSLog(@"ClientBlue 订阅成功：%@", characteristic.UUID.UUIDString);
    [self toFlutterType:ClientStateType code:@(8) msg:@"连接成功"];
  } else {
    NSLog(@"ClientBlue 取消订阅：%@", characteristic.UUID.UUIDString);
      [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    self.isConnecting = false;
  }
}

- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices{
    NSLog(@"ClientBlue 服务无效了：%@", invalidatedServices);
    [self toFlutterType:ClientStateType code:@(10) msg:@"连接失败"];
    self.isConnecting = false;
}

// 收到消息
- (void)peripheral: (CBPeripheral *)peripheral didUpdateValueForCharacteristic: (CBCharacteristic *)characteristic error: (NSError *)error {
  if (error) {
    NSLog(@"ClientBlue 更新特征值错误：%@", error.localizedDescription);
    return;
  }
  // 判断是否是要订阅的特征
  if ([characteristic.UUID isEqual:self.characteristicUUID]) {
    // 获取特征的值，一般是 NSData 类型
    NSData *data = characteristic.value;
    // 转换成字符串
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    // 打印出来
    NSLog(@"ClientBlue 收到特征更新：%@", string);
    [self toFlutterType:ServerMsgType code:@(1) msg:string];
  }
}

// 当写入特征的值时的回调，一般是服务端的响应
- (void)peripheral: (CBPeripheral *)peripheral didWriteValueForCharacteristic: (CBCharacteristic *)characteristic error: (NSError *)error {
  if (error) {
    NSLog(@"ClientBlue 写入特征值错误：%@", error.localizedDescription);
    return;
  }
  // 判断是否是要订阅的特征
  if ([characteristic.UUID isEqual:self.characteristicUUID]) {
    // 打印出服务端的响应
    NSLog(@"ClientBlue 服务端已响应：%@", characteristic.UUID.UUIDString);
  }
}

@end
